package com.jrx.anytxn.transaction.handler.impl;

import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.exception.TxnRuntimeException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.customer.entity.CmCustomerFirstLevel;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.param.entity.PrChannelTable;
import com.jrx.anytxn.param.entity.PrInterestTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrPenaltyRateTable;
import com.jrx.anytxn.param.mapper.ext.ExtBtBatchStatusMapper;
import com.jrx.anytxn.param.service.product.IInterestTableService;
import com.jrx.anytxn.param.service.product.IPrPenaltyRateTableService;
import com.jrx.anytxn.param.service.system.IChannelTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.transaction.bean.ManuallyAdjustAccountSaveBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.constant.TransErrMsgConstant;
import com.jrx.anytxn.transaction.dto.manuallyTransaction.AdjustAmountReq;
import com.jrx.anytxn.transaction.dto.manuallyTransaction.LoanOrderRes;
import com.jrx.anytxn.transaction.entity.AmAccountMainInfo;
import com.jrx.anytxn.transaction.entity.AmInterestAccrualInfo;
import com.jrx.anytxn.transaction.entity.AmLoanAccountInfo;
import com.jrx.anytxn.transaction.entity.AmLoanMainInfo;
import com.jrx.anytxn.transaction.entity.AmRepaymentPlanInfo;
import com.jrx.anytxn.transaction.entity.TlGlInterfaceInfo;
import com.jrx.anytxn.transaction.entity.TlTransactionInfo;
import com.jrx.anytxn.transaction.handler.IManuallyTransactionHandler;
import com.jrx.anytxn.transaction.mapper.base.TlTransactionInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmAccountMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmInterestAccrualInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanAccountInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmRepaymentPlanInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlGlInterfaceInfoMapper;
import com.jrx.anytxn.transaction.service.IGlInterfaceService;
import com.jrx.anytxn.transaction.service.ITlTransactionInfoService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 手工交易handler实现
 *
 * @author : zhenghaopu
 * 2020/1/16
 */
@Component
public class ManuallyTransactionHandlerImpl implements IManuallyTransactionHandler {

    private static final Logger logger = LoggerFactory.getLogger(ManuallyTransactionHandlerImpl.class);

    @Autowired
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;

    @Autowired
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;

    @Autowired
    private IChannelTableService channelTableService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private IOrganizationTableService organizationTableService;

    @Autowired
    private ExtBtBatchStatusMapper extBtBatchStatusMapper;

    @Autowired
    private ITlTransactionInfoService transactionInfoService;

    @Autowired
    private ExtAmAccountMainInfoMapper extAmAccountMainInfoMapper;

    @Autowired
    private ExtAmInterestAccrualInfoMapper extAmInterestAccrualInfoMapper;

    @Autowired
    private IGlInterfaceService glInterfaceService;

    @Autowired
    private ExtAmRepaymentPlanInfoMapper extAmRepaymentPlanInfoMapper;

    @Autowired
    private TlTransactionInfoMapper tlTransactionInfoMapper;

    @Autowired
    private ExtTlGlInterfaceInfoMapper extTlGlInterfaceInfoMapper;

    @Autowired
    private IInterestTableService interestTableService;

    @Autowired
    private IPrPenaltyRateTableService penaltyRateTableService;

    @Override
    public List<LoanOrderRes> getOrderList(String tenantId, String queryType, String queryParam) throws TxnException {

        //若查询类型为订单号
        if(TransBizConstant.MT_QUERY_TYPE_2.equals(queryType)){
            //根据租户与订单号查询订单数据
            AmLoanMainInfo loanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(queryParam,tenantId);
            if(loanMainInfo == null){
                logger.error(TransErrMsgConstant.NO_LOAN);
                throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getUserTips());
            }
            //查询账户信息
            AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(loanMainInfo.getLoanId(),
                    loanMainInfo.getCustomerId(),tenantId);

            //查询渠道信息
            PrChannelTable channelTable =
                    channelTableService.getChannelTableByChannelIdAndStatus(TransBizConstant.YES_FLAG,
                            loanMainInfo.getChannel(),tenantId);

            //查询用户信息
            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(loanMainInfo.getCustomerId(),
                    loanMainInfo.getOrganizationId(),loanMainInfo.getTenantId());

            //构建返回信息
            LoanOrderRes loanOrderRes = BeanMapping.copy(loanMainInfo, LoanOrderRes.class);
            loanOrderRes.setChannelName(channelTable.getChineseName());
            loanOrderRes.setCustomerName(firstLevel.getChineseName());
            loanOrderRes.setAccountStatus(amLoanAccountInfo.getAccountStatus());
            List<LoanOrderRes> loanOrderResList = new ArrayList<>(1);
            loanOrderResList.add(loanOrderRes);
            return  loanOrderResList;
        }else{//查询类型是手机号或证件号
            List<LoanOrderRes> loanOrderResList =new ArrayList<>();
            List<CmCustomerFirstLevel> customerFirstLevelList = null;
            if(TransBizConstant.MT_QUERY_TYPE_1.equals(queryType)){//若使用手机号查询
                customerFirstLevelList = customerService.getCustomerList(queryParam,null,tenantId);
            }else{//若是使用证件号查询
                customerFirstLevelList = customerService.getCustomerList(null,queryParam,tenantId);
            }

            //循坏客户id列表 查询订单信息
            for(CmCustomerFirstLevel customerFirstLevel : customerFirstLevelList){
                List<AmLoanMainInfo> loanMainInfoList =
                        extAmLoanMainInfoMapper.selectByCusIdtAndTenantId(customerFirstLevel.getCustomerId(), tenantId);
                //若查没有询到相关订单 跳过继续查询
                if(CollectionUtils.isEmpty(loanMainInfoList)){
                    continue;
                }
                //订单idList
                List<String> loanIdList = loanMainInfoList.stream().map(AmLoanMainInfo::getLoanId).collect(Collectors.toList());
                //查询贷款账户信息
                List<AmLoanAccountInfo> loanAccountInfoList =
                        extAmLoanAccountInfoMapper.selectByLoanIdsAndTenanIdAndCusId(loanIdList,tenantId,customerFirstLevel.getCustomerId());
                //转换账户信息为map key->订单id value->状态
                Map<String,String> loanAccMap =
                        loanAccountInfoList.stream().collect(Collectors.toMap(AmLoanAccountInfo::getLoanId,
                                AmLoanAccountInfo::getAccountStatus));
                //循环并且创建返回对象
                for(AmLoanMainInfo loanMainInfo : loanMainInfoList){
                    //构建返回信息
                    LoanOrderRes loanOrderRes = BeanMapping.copy(loanMainInfo, LoanOrderRes.class);
                    //获取渠道信息
                    PrChannelTable channelTable =
                            channelTableService.getChannelTableByChannelIdAndStatus(TransBizConstant.YES_FLAG,
                                    loanMainInfo.getChannel(), tenantId);
                    loanOrderRes.setChannelName(channelTable.getChineseName());
                    loanOrderRes.setCustomerName(customerFirstLevel.getChineseName());
                    loanOrderRes.setAccountStatus(loanAccMap.get(loanMainInfo.getLoanId()));
                    loanOrderResList.add(loanOrderRes);
                }
            }
            return  loanOrderResList;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void adjustAmount(AdjustAmountReq adjustAmountReq, String tenantId, String userId) throws TxnException {

        //要更新的信息
        ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean = new ManuallyAdjustAccountSaveBean();

        //判断是否在批处理中
        Date businessDate = validateBatchProcessing(tenantId,adjustAmountReq.getOrganizationId());

        //根据输入账户类型进行调整
        switch (adjustAmountReq.getAccountType()){
            case TransBizConstant.MT_ADJUST_TYPE_INTEREST: adjustInterestAmt(adjustAmountReq,tenantId, businessDate,
                    manuallyAdjustAccountSaveBean,userId);break;
            case TransBizConstant.MT_ADJUST_TYPE_FEE: adjustFeeAmt(adjustAmountReq,tenantId, businessDate,
                    manuallyAdjustAccountSaveBean,userId);break;
            case TransBizConstant.MT_ADJUST_TYPE_PENALTY: adjustPenaltyAmt(adjustAmountReq,tenantId, businessDate,
                    manuallyAdjustAccountSaveBean,userId);break;
            case TransBizConstant.MT_ADJUST_TYPE_COMPOUND: adjustCompoundAmt(adjustAmountReq,tenantId, businessDate,
                    manuallyAdjustAccountSaveBean,userId);break;
            default:logger.error(TransErrMsgConstant.ADJUST_TYPE_ERROR);
            throw new TxnRuntimeException(TxnRespCode.BIZ_ERROR.getCode(),
                    TxnRespCode.BIZ_ERROR.getUserTips());
        }
        //保存更新信息
        updateManuallyAdjustInfo(manuallyAdjustAccountSaveBean);
    }

    /**
     * 利息调整
     * @param adjustAmountReq
     * @param tenantId
     */
    private void adjustInterestAmt(AdjustAmountReq adjustAmountReq, String tenantId,Date businessDate,
                                   ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean, String userId) throws TxnException {
        //构建交易信息
        TlTransactionInfo initTransactionInfo = BeanMapping.copy(adjustAmountReq, TlTransactionInfo.class);
        initTransactionInfo.setTenantId(tenantId);
        initTransactionInfo.setPostingDate(businessDate);
        //订单账户调整
        AmLoanAccountInfo loanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(adjustAmountReq.getLoanId(),
                adjustAmountReq.getCustomerId(), tenantId);
        String txnCode = TransBizConstant.TXN_CODE_INST_INTR_T;
        String txnCode2 = TransBizConstant.TXN_CODE_INTR_REVOCATION;
        if (TransBizConstant.NON_ACCRUALS_FLA_1.equalsIgnoreCase(loanAccountInfo.getNonAccrualsFlag())) {
            txnCode = txnCode.replaceFirst("5", "9");
            txnCode2 = txnCode2.replaceFirst("5", "9");

        }
        TlTransactionInfo transactionInfo = transactionInfoService.buildTlTransactionInfo(initTransactionInfo,
                txnCode, TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
        transactionInfo.setUpdateBy(userId);

        //查询当期所有正常或逾期状态的利息交易账户
        List<String> statusList = Arrays.asList(TransBizConstant.ACCOUNT_STATUS_1, TransBizConstant.ACCOUNT_STATUS_2);
        List<AmAccountMainInfo> accountMainInfoList =
                extAmAccountMainInfoMapper.selectByLoanIdAndTypeAndCustomerIdAndBillingTenorAndStatusIn(
                        adjustAmountReq.getLoanId(), TransBizConstant.ACCOUNT_TYPE_04, adjustAmountReq.getCustomerId(),
                        adjustAmountReq.getBillingTenor(), statusList, null, tenantId);
        //新建总账流水list
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        //要更新的交易账户list
        List<AmAccountMainInfo> updateAccList = new ArrayList<>();

        //调整剩余金额
        BigDecimal currAdjustAmt = adjustAmountReq.getPostingAmount();
        //利息交易账户调整金额
        BigDecimal interestAmt = BigDecimal.ZERO;

        //若交易账户不为空 调整交易信息
        if (CollectionUtils.isNotEmpty(accountMainInfoList)) {
            for (AmAccountMainInfo accountMainInfo : accountMainInfoList) {//判断调整金额与余额大小
                AmAccountMainInfo updateAcc = buildUpdateAcct(accountMainInfo);//获取要更新的交易账户
                updateAcc.setUpdateBy(userId);
                BigDecimal taxAmt = BigDecimal.ZERO;
                PrInterestTable prInterestTable = interestTableService.findInterestByInterestId(accountMainInfo.getInterestTableId(), accountMainInfo.getTenantId());
                //若调整金额大于当前账户余额 则调整金额为余额
                if (currAdjustAmt.compareTo(accountMainInfo.getCurrBalance()) > 0) {
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(accountMainInfo.getCurrBalance()));//调整金额
                    updateAcc.setCurrBalance(BigDecimal.ZERO);//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prInterestTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = accountMainInfo.getCurrBalance().multiply(prInterestTable.getTaxRate()).divide(BigDecimal.ONE.add(prInterestTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }
                    //构建总账流水
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            accountMainInfo.getCurrBalance().subtract(taxAmt), txnCode,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    currAdjustAmt = currAdjustAmt.subtract(accountMainInfo.getCurrBalance());//更新调额剩余金额
                    interestAmt = interestAmt.add(accountMainInfo.getCurrBalance());//更新已抛利息金额
                } else { //若调整金额小等于当前账户余额
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(currAdjustAmt));//调整金额
                    updateAcc.setCurrBalance(accountMainInfo.getCurrBalance().subtract(currAdjustAmt));//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prInterestTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = currAdjustAmt.multiply(prInterestTable.getTaxRate()).divide(BigDecimal.ONE.add(prInterestTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }
                    //构建总账流水
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            currAdjustAmt.subtract(taxAmt), txnCode,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                        manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);
                    }
                    interestAmt = interestAmt.add(currAdjustAmt);//更新已抛利息金额
                    currAdjustAmt = BigDecimal.ZERO;//更新调额剩余金额为0
                }

                updateAcc.setTaxAmt(accountMainInfo.getTaxAmt().subtract(taxAmt));
                updateAccList.add(updateAcc); //放入更新列表
                manuallyAdjustAccountSaveBean.setUpdateAccList(updateAccList);
                TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTaxTlGlInterfaceInfo(accountMainInfo, currAdjustAmt,taxAmt, TransBizConstant.TXN_CODE_INST_INTR_TAX_T, accountMainInfo.getAccountingPhase(), businessDate);
                if (glInterfaceInfo != null) {
                    glInterfaceInfo.setUpdateBy(userId);
                    glInterfaceInfoList.add(glInterfaceInfo);
                    manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);
                }

                if (currAdjustAmt.compareTo(BigDecimal.ZERO) == 0) {
                    break;
                }
            }
            manuallyAdjustAccountSaveBean.setAddTransInfo(transactionInfo);//交易信息
        }

        //利息累计账户调整金额
        BigDecimal accrualAmt = BigDecimal.ZERO;
        //若交易账户调整后 剩余调整金额大于0  继续调整累计账户
        if (currAdjustAmt.compareTo(BigDecimal.ZERO) > 0) {
            //处理累计账户
            List<AmInterestAccrualInfo> interestAccrualInfoList =
                    extAmInterestAccrualInfoMapper.selectAccuAcct(adjustAmountReq.getLoanId(),
                            adjustAmountReq.getCustomerId(), tenantId, TransBizConstant.INTEREST_ACCRUAL_TYPE_66,
                            adjustAmountReq.getBillingTenor(), TransBizConstant.ACCOUNT_STATUS_1);

            if (CollectionUtils.isNotEmpty(interestAccrualInfoList)) {
                interestAccrualInfoList.sort(Comparator.comparing(AmInterestAccrualInfo::getAccrualStartDate).reversed());

                //调整交易功能中，调整累计账户时，查询出为list，根据accrual_start_date交易起息日从大到小排序，逐个调整
                for (AmInterestAccrualInfo interestAccrualInfo : interestAccrualInfoList) {
                    //构建要更新的累计账户信息
                    AmInterestAccrualInfo updateAccrual = buildUpdateAccrual(interestAccrualInfo);
                    updateAccrual.setAccountType(interestAccrualInfo.getAccountType());
                    updateAccrual.setMaxInterest(interestAccrualInfo.getMaxInterest().subtract(currAdjustAmt));//最大利息金额（max_interest）减去当前账户调整金额；
                    updateAccrual.setUpdateBy(userId);
                    //若调整后最大利息金额小于已累计总利息
                    if (updateAccrual.getMaxInterest().compareTo(interestAccrualInfo.getAccrualTotalAccruInterest()) < 0) {
                        //价税分离
                        BigDecimal taxAmt = BigDecimal.ZERO;
                        PrInterestTable prInterestTable = interestTableService.findInterestByInterestId(interestAccrualInfo.getInterestTableId(), interestAccrualInfo.getTenantId());
                        if (TransBizConstant.TAX_FLAG_0.equals(prInterestTable.getTaxFlag())) {
                            //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                            BigDecimal intrAmt = interestAccrualInfo.getAccrualTotalAccruInterest().subtract(updateAccrual.getMaxInterest());
                            taxAmt =intrAmt.multiply(prInterestTable.getTaxRate()).divide(BigDecimal.ONE.add(prInterestTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                            updateAccrual.setTaxAmt(interestAccrualInfo.getTaxAmt().subtract(taxAmt));

                            TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTaxTlGlInterfaceInfo(interestAccrualInfo, intrAmt,taxAmt, TransBizConstant.TXN_CODE_INTR_TAX_REVOCATION, interestAccrualInfo.getAccountingPhase(), businessDate);
                            if (glInterfaceInfo != null) {
                                glInterfaceInfo.setUpdateBy(userId);
                                glInterfaceInfoList.add(glInterfaceInfo);
                            }
                        }

                        //构建总账流水
                        TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(interestAccrualInfo,
                                interestAccrualInfo.getAccrualTotalAccruInterest().subtract(updateAccrual.getMaxInterest()).subtract(taxAmt),
                                txnCode2, interestAccrualInfo.getAccountingPhase(), businessDate);
                        if (glInterfaceInfo != null) {
                            glInterfaceInfo.setUpdateBy(userId);
                            glInterfaceInfoList.add(glInterfaceInfo);
                        }
                        accrualAmt = accrualAmt.add(interestAccrualInfo.getAccrualTotalAccruInterest().subtract(updateAccrual.getMaxInterest()));//更新利息累计账户调整金额
                        updateAccrual.setAccrualTotalAccruInterest(updateAccrual.getMaxInterest());
                    }
                    manuallyAdjustAccountSaveBean.addUpdateAccral(updateAccrual);
                }
            }

            //查询还款计划
            AmRepaymentPlanInfo repaymentPlanInfo =
                    extAmRepaymentPlanInfoMapper.selectByLoanIdAndBillingTenor(adjustAmountReq.getLoanId(),
                            adjustAmountReq.getCustomerId(), tenantId, adjustAmountReq.getBillingTenor(),
                            Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_0, TransBizConstant.LOAN_PLAN_STATUS_1,
                                    TransBizConstant.LOAN_PLAN_STATUS_2));
            AmRepaymentPlanInfo updateRepaymentPlan = buildUpdateRepaymentPlan(repaymentPlanInfo);//要更新的还款计划
            updateRepaymentPlan.setUpdateBy(userId);
            if (TransBizConstant.LOAN_PLAN_STATUS_2.equals(repaymentPlanInfo.getPlanStatus())) {
                updateRepaymentPlan.setOverDueAmount(repaymentPlanInfo.getOverDueAmount().subtract(interestAmt));
                updateRepaymentPlan.setInterestAmount(repaymentPlanInfo.getInterestAmount().subtract(interestAmt));
                updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(interestAmt));
            } else if (TransBizConstant.LOAN_PLAN_STATUS_0.equals(repaymentPlanInfo.getPlanStatus())) {
                updateRepaymentPlan.setInterestAmount(repaymentPlanInfo.getInterestAmount().subtract(adjustAmountReq.getPostingAmount()));
                updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(adjustAmountReq.getPostingAmount()));
            } else {
                AmInterestAccrualInfo updateInterAcct = manuallyAdjustAccountSaveBean.getUpdateAccralList().stream()
                        .filter(inte-> inte.getAccountType().equalsIgnoreCase(TransBizConstant.INTEREST_ACCRUAL_TYPE_66)).findFirst().get();

                updateRepaymentPlan.setInterestAmount(updateInterAcct.getMaxInterest());//当期利息
                //利息变化值 = 原利息 - 要更新的利息累计最大值
                BigDecimal diffAmt =
                        repaymentPlanInfo.getInterestAmount().subtract(updateInterAcct.getMaxInterest());
                updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(diffAmt));
            }


            //对已抛期数进行调整
            if (repaymentPlanInfo.getBillingTenor() <= loanAccountInfo.getCastTenor()) {
                AmLoanAccountInfo updateLoanAcct = buildUpdateLoanAcct(loanAccountInfo);//要更新的贷款账户
                updateLoanAcct.setUpdateBy(userId);
                updateLoanAcct.setCurrBalance(loanAccountInfo.getCurrBalance().subtract(interestAmt));//余额
                updateLoanAcct.setInterestBalance(loanAccountInfo.getInterestBalance().subtract(interestAmt));//利息余额
                updateLoanAcct.setAccruedInterest(loanAccountInfo.getAccruedInterest().subtract(accrualAmt));//计提利息

                manuallyAdjustAccountSaveBean.setUpdateLoanAcct(updateLoanAcct);//贷款账户信息
                manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);//总账信息
                manuallyAdjustAccountSaveBean.setUpdateAccList(updateAccList);//交易账户信息
            }
            manuallyAdjustAccountSaveBean.setUpdateRepaymentPlanInfo(updateRepaymentPlan);//还款计划

            //复利计息基础调整
            AmInterestAccrualInfo compAccuAcct = extAmInterestAccrualInfoMapper.selectAccuAcctNotStopping(adjustAmountReq.getLoanId(),
                    adjustAmountReq.getCustomerId(), tenantId, TransBizConstant.INTEREST_ACCRUAL_TYPE_20,
                    adjustAmountReq.getBillingTenor(), TransBizConstant.ACCOUNT_STATUS_1);
            if (null != compAccuAcct) {
                AmInterestAccrualInfo updateCompAccuAcct = new AmInterestAccrualInfo();
                updateCompAccuAcct.setId(compAccuAcct.getId());
                updateCompAccuAcct.setCustomerId(compAccuAcct.getCustomerId());
                updateCompAccuAcct.setTenantId(compAccuAcct.getTenantId());
                updateCompAccuAcct.setAccrualBaseAmount(compAccuAcct.getAccrualBaseAmount().subtract(adjustAmountReq.getPostingAmount()));
                manuallyAdjustAccountSaveBean.addUpdateAccral(updateCompAccuAcct);
            }
        }
    }

    /**
     * 费用调整
     * @param adjustAmountReq
     * @param tenantId
     */
    private void adjustFeeAmt(AdjustAmountReq adjustAmountReq, String tenantId,Date businessDate,
                              ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean, String userId) throws TxnException {
        //构建交易信息
        TlTransactionInfo initTransactionInfo = BeanMapping.copy(adjustAmountReq,TlTransactionInfo.class);
        initTransactionInfo.setTenantId(tenantId);
        initTransactionInfo.setPostingDate(businessDate);
        TlTransactionInfo transactionInfo = transactionInfoService.buildTlTransactionInfo(initTransactionInfo,
                TransBizConstant.TXN_CODE_INST_FEE_T,TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
        transactionInfo.setUpdateBy(userId);
        //查询当期所有正常或逾期状态的费用交易账户
        List<String> statusList = Arrays.asList(TransBizConstant.ACCOUNT_STATUS_1,TransBizConstant.ACCOUNT_STATUS_2);
        List<AmAccountMainInfo> accountMainInfoList =
                extAmAccountMainInfoMapper.selectByLoanIdAndTypeAndCustomerIdAndBillingTenorAndStatusIn(
                        adjustAmountReq.getLoanId(), TransBizConstant.ACCOUNT_TYPE_03, adjustAmountReq.getCustomerId(),
                        adjustAmountReq.getBillingTenor(),statusList,TransBizConstant.TXN_CODE_INST_FEE,tenantId);
        //新建总账流水list
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        //要更新的交易账户list
        List<AmAccountMainInfo> updateAccList =new ArrayList<>();

        //调整剩余金额
        BigDecimal currAdjustAmt = adjustAmountReq.getPostingAmount();
        //费用交易账户调整金额
        BigDecimal feeAmt = BigDecimal.ZERO;
        //若交易账户不为空 调整交易信息
        if(CollectionUtils.isNotEmpty(accountMainInfoList)){
            for (AmAccountMainInfo accountMainInfo : accountMainInfoList) {
                AmAccountMainInfo updateAcc = buildUpdateAcct(accountMainInfo);//获取要更新的交易账户
                updateAcc.setUpdateBy(userId);
                //若调整金额大于当前账户余额 则调整金额为余额
                if (currAdjustAmt.compareTo(accountMainInfo.getCurrBalance()) > 0) {
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(accountMainInfo.getCurrBalance()));//调整金额
                    updateAcc.setCurrBalance(BigDecimal.ZERO);//余额
                    updateAccList.add(updateAcc);
                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            accountMainInfo.getCurrBalance(),TransBizConstant.TXN_CODE_INST_FEE_T,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if(tlGlInterfaceInfo !=null){
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    currAdjustAmt = currAdjustAmt.subtract(accountMainInfo.getCurrBalance());//更新剩余调整金额
                    feeAmt=feeAmt.add(accountMainInfo.getCurrBalance());//更新已抛利息金额
                }else{ //若调整金额小等于当前账户余额
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(currAdjustAmt));//调整金额
                    updateAcc.setCurrBalance(accountMainInfo.getCurrBalance().subtract(currAdjustAmt));//余额
                    updateAccList.add(updateAcc);
                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            currAdjustAmt,TransBizConstant.TXN_CODE_INST_FEE_T,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if(tlGlInterfaceInfo !=null){
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    feeAmt=feeAmt.add(currAdjustAmt);//更新已抛利息金额
                    break;
                }
            }
        }
        //查询还款计划
        AmRepaymentPlanInfo repaymentPlanInfo =
                extAmRepaymentPlanInfoMapper.selectByLoanIdAndBillingTenor(adjustAmountReq.getLoanId(),
                        adjustAmountReq.getCustomerId(),tenantId,adjustAmountReq.getBillingTenor(),
                        Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_0,TransBizConstant.LOAN_PLAN_STATUS_1,
                                TransBizConstant.LOAN_PLAN_STATUS_2));
        AmRepaymentPlanInfo updateRepaymentPlan =buildUpdateRepaymentPlan(repaymentPlanInfo);//要更新的还款计划
        updateRepaymentPlan.setUpdateBy(userId);
        updateRepaymentPlan.setFeeAmount(repaymentPlanInfo.getFeeAmount().subtract(feeAmt));
        updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(feeAmt));
        if(TransBizConstant.LOAN_PLAN_STATUS_0.equals(repaymentPlanInfo.getPlanStatus())){
            updateRepaymentPlan.setFeeAmount(repaymentPlanInfo.getFeeAmount().subtract(adjustAmountReq.getPostingAmount()));
            updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(adjustAmountReq.getPostingAmount()));
        }else if(TransBizConstant.LOAN_PLAN_STATUS_2.equals(repaymentPlanInfo.getPlanStatus())){
            updateRepaymentPlan.setOverDueAmount(repaymentPlanInfo.getOverDueAmount().subtract(feeAmt));
            updateRepaymentPlan.setFeeAmount(repaymentPlanInfo.getFeeAmount().subtract(feeAmt));
            updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(feeAmt));
        }else{
            updateRepaymentPlan.setFeeAmount(repaymentPlanInfo.getFeeAmount().subtract(feeAmt));
            updateRepaymentPlan.setTotalAmount(repaymentPlanInfo.getTotalAmount().subtract(feeAmt));
        }

        //订单账户调整
        AmLoanAccountInfo loanAccountInfo= extAmLoanAccountInfoMapper.selectByLoanId(adjustAmountReq.getLoanId(),
                adjustAmountReq.getCustomerId(),tenantId);
        //对已抛期数进行调整
        if(repaymentPlanInfo.getBillingTenor()<= loanAccountInfo.getCastTenor()){
            AmLoanAccountInfo updateLoanAcct =  buildUpdateLoanAcct(loanAccountInfo);//要更新的贷款账户
            updateLoanAcct.setUpdateBy(userId);
            updateLoanAcct.setCurrBalance(loanAccountInfo.getCurrBalance().subtract(feeAmt));//余额
            updateLoanAcct.setFeeBalance(loanAccountInfo.getFeeBalance().subtract(feeAmt));//费用余额

            manuallyAdjustAccountSaveBean.setUpdateLoanAcct(updateLoanAcct);//贷款账户信息
            manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);//总账信息
            manuallyAdjustAccountSaveBean.setUpdateAccList(updateAccList);//交易账户信息
        }

        manuallyAdjustAccountSaveBean.setAddTransInfo(transactionInfo);//交易信息
        manuallyAdjustAccountSaveBean.setUpdateRepaymentPlanInfo(updateRepaymentPlan);//还款计划

    }

    //罚息调整
    private void adjustPenaltyAmt(AdjustAmountReq adjustAmountReq, String tenantId, Date businessDate,
                                             ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean, String userId) throws TxnException {
        //构建交易信息
        TlTransactionInfo initTransactionInfo = BeanMapping.copy(adjustAmountReq, TlTransactionInfo.class);
        initTransactionInfo.setTenantId(tenantId);
        initTransactionInfo.setPostingDate(businessDate);
        //订单账户调整
        AmLoanAccountInfo loanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(adjustAmountReq.getLoanId(),
                adjustAmountReq.getCustomerId(), tenantId);
        String txnCode = TransBizConstant.TXN_CODE_INST_PEN_INTR_T;
        String txnCode2 = TransBizConstant.TXN_CODE_PENT_INTR_REVOCATION;
        if (TransBizConstant.NON_ACCRUALS_FLA_1.equalsIgnoreCase(loanAccountInfo.getNonAccrualsFlag())) {
            txnCode = txnCode.replaceFirst("5", "9");
            txnCode2 = txnCode2.replaceFirst("5", "9");

        }
        TlTransactionInfo transactionInfo = transactionInfoService.buildTlTransactionInfo(initTransactionInfo,
                txnCode, TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
        transactionInfo.setUpdateBy(userId);
        //查询当期所有正常或逾期状态的费用交易账户
        List<String> statusList = Arrays.asList(TransBizConstant.ACCOUNT_STATUS_1, TransBizConstant.ACCOUNT_STATUS_2);
        List<AmAccountMainInfo> accountMainInfoList =
                extAmAccountMainInfoMapper.selectByLoanIdAndTypeAndCustomerIdAndBillingTenorAndStatusIn(
                        adjustAmountReq.getLoanId(), TransBizConstant.ACCOUNT_TYPE_11, adjustAmountReq.getCustomerId(),
                        adjustAmountReq.getBillingTenor(), statusList, null, tenantId);
        //新建总账流水list
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        //要更新的交易账户list
        List<AmAccountMainInfo> updateAccList = new ArrayList<>();

        //调整剩余金额
        BigDecimal currAdjustAmt = adjustAmountReq.getPostingAmount();
        //罚息交易账户调整金额
        BigDecimal penaltyAmt = BigDecimal.ZERO;

        //若交易账户不为空 调整交易信息
        if (CollectionUtils.isNotEmpty(accountMainInfoList)) {
            for (AmAccountMainInfo accountMainInfo : accountMainInfoList) {
                AmAccountMainInfo updateAcc = buildUpdateAcct(accountMainInfo);//获取要更新的交易账户
                updateAcc.setUpdateBy(userId);
                BigDecimal taxAmt = BigDecimal.ZERO;
                PrPenaltyRateTable prPenaltyRateTable = penaltyRateTableService.findByPenaltyId(accountMainInfo.getPenaltyTableId(), accountMainInfo.getOrganizationId(), accountMainInfo.getTenantId());
                //若调整金额大于当前账户余额 则调整金额为余额
                if (currAdjustAmt.compareTo(accountMainInfo.getCurrBalance()) > 0) {
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(accountMainInfo.getCurrBalance()));//调整金额
                    updateAcc.setCurrBalance(BigDecimal.ZERO);//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = accountMainInfo.getCurrBalance().multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }
                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            accountMainInfo.getCurrBalance().subtract(taxAmt), txnCode,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    penaltyAmt = penaltyAmt.add(accountMainInfo.getCurrBalance());//更新罚息交易账户调整金额
                    currAdjustAmt = currAdjustAmt.subtract(accountMainInfo.getCurrBalance());//更新剩余调整金额
                } else { //若调整金额小等于当前账户余额
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(currAdjustAmt));//调整金额
                    updateAcc.setCurrBalance(accountMainInfo.getCurrBalance().subtract(currAdjustAmt));//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = currAdjustAmt.multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }
                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            currAdjustAmt.subtract(taxAmt), txnCode,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    penaltyAmt = penaltyAmt.add(currAdjustAmt);//更新罚息交易账户调整金额
                    currAdjustAmt = BigDecimal.ZERO;//更新剩余调整金额为0
                }

                updateAcc.setTaxAmt(accountMainInfo.getTaxAmt().subtract(taxAmt));
                updateAccList.add(updateAcc); //放入更新列表
                TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo, taxAmt, TransBizConstant.TXN_CODE_INST_PEN_INTR_TAX_T, accountMainInfo.getAccountingPhase(), businessDate);
                if (glInterfaceInfo != null) {
                    glInterfaceInfo.setUpdateBy(userId);
                    glInterfaceInfoList.add(glInterfaceInfo);
                }


                if (currAdjustAmt.compareTo(BigDecimal.ZERO) == 0) {
                    break;
                }
            }
        }
        //罚息累计账户调整金额
        BigDecimal accrualAmt = BigDecimal.ZERO;
        //若交易账户调整后 剩余调整金额大于0  继续调整累计账户
        BigDecimal remainAmt = currAdjustAmt;
        if (currAdjustAmt.compareTo(BigDecimal.ZERO) > 0) {
            //处理累计账户
            List<AmInterestAccrualInfo> interestAccrualInfoList =
                    extAmInterestAccrualInfoMapper.selectAccuAcct(adjustAmountReq.getLoanId(),
                            adjustAmountReq.getCustomerId(), tenantId, TransBizConstant.INTEREST_ACCRUAL_TYPE_10,
                            adjustAmountReq.getBillingTenor(), TransBizConstant.ACCOUNT_STATUS_1);


            if (CollectionUtils.isNotEmpty(interestAccrualInfoList)) {
                interestAccrualInfoList.sort(Comparator.comparing(AmInterestAccrualInfo::getAccrualStartDate).reversed());

                //罚息累计不为空 修正罚息累计
                for (AmInterestAccrualInfo interestAccrualInfo : interestAccrualInfoList) {
                    //构建要更新的累计账户信息
                    AmInterestAccrualInfo updateAccrual = buildUpdateAccrual(interestAccrualInfo);
                    updateAccrual.setUpdateBy(userId);
                    // 获取已累计总利息
                    BigDecimal accrualTotalAccruInterest = interestAccrualInfo.getAccrualTotalAccruInterest();
                    if (remainAmt.compareTo(accrualTotalAccruInterest) >= 0) {
                        remainAmt = remainAmt.subtract(accrualTotalAccruInterest);
                        // 当前需要调整的金额
                        currAdjustAmt = accrualTotalAccruInterest;
                        updateAccrual.setAccrualTotalAccruInterest(BigDecimal.ZERO);
                    } else {
                        updateAccrual.setAccrualTotalAccruInterest(accrualTotalAccruInterest.subtract(remainAmt));
                        // 当前需要调整的金额
                        currAdjustAmt = remainAmt;
                        remainAmt = BigDecimal.ZERO;
                    }
                    //价税分离
                    BigDecimal taxAmt = BigDecimal.ZERO;
                    PrInterestTable prPenaltyRateTable = interestTableService.findInterestByInterestId(interestAccrualInfo.getInterestTableId(), interestAccrualInfo.getTenantId());
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = currAdjustAmt.multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                        updateAccrual.setTaxAmt(interestAccrualInfo.getTaxAmt().subtract(taxAmt));
                        TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(interestAccrualInfo, taxAmt, TransBizConstant.TXN_CODE_PENT_INTR_TAX_REVOCATION, interestAccrualInfo.getAccountingPhase(), businessDate);
                        if (glInterfaceInfo != null) {
                            glInterfaceInfo.setUpdateBy(userId);
                            glInterfaceInfoList.add(glInterfaceInfo);
                        }
                    }

                    manuallyAdjustAccountSaveBean.addUpdateAccral(updateAccrual);
                    //构建总账信息
                    TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(interestAccrualInfo, currAdjustAmt.subtract(taxAmt),
                            txnCode2, interestAccrualInfo.getAccountingPhase(), businessDate);
                    if (glInterfaceInfo != null) {
                        glInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(glInterfaceInfo);
                    }
                    accrualAmt = accrualAmt.add(currAdjustAmt);//更新罚息累计账户调整金额
                    if (remainAmt.compareTo(BigDecimal.ZERO) == 0) {
                        break;
                    }
                }
            }
        }
        //订单账户调整
        if (adjustAmountReq.getBillingTenor() <= loanAccountInfo.getCastTenor()) {
            AmLoanAccountInfo updateLoanAcct = buildUpdateLoanAcct(loanAccountInfo);//要更新的贷款账户
            updateLoanAcct.setUpdateBy(userId);
            updateLoanAcct.setPenaltyBalance(loanAccountInfo.getPenaltyBalance().subtract(penaltyAmt));//罚息余额
            updateLoanAcct.setAccruedPenalty(loanAccountInfo.getAccruedPenalty().subtract(accrualAmt));//计提罚息
            manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);//总账信息
            manuallyAdjustAccountSaveBean.setUpdateAccList(updateAccList);//交易账户信息
            manuallyAdjustAccountSaveBean.setUpdateLoanAcct(updateLoanAcct);//贷款账户信息
        }

        manuallyAdjustAccountSaveBean.setAddTransInfo(transactionInfo);//交易信息
    }

    //复利调整
    private void adjustCompoundAmt(AdjustAmountReq adjustAmountReq, String tenantId, Date businessDate,
                                   ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean, String userId) throws TxnException {
        //构建交易信息
        TlTransactionInfo initTransactionInfo = BeanMapping.copy(adjustAmountReq, TlTransactionInfo.class);
        initTransactionInfo.setTenantId(tenantId);
        initTransactionInfo.setPostingDate(businessDate);
        TlTransactionInfo transactionInfo = transactionInfoService.buildTlTransactionInfo(initTransactionInfo,
                TransBizConstant.TXN_CODE_INST_COMP_INTR_T, TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
        transactionInfo.setUpdateBy(userId);
        //查询当期所有正常或逾期状态的复利交易账户
        List<String> statusList = Arrays.asList(TransBizConstant.ACCOUNT_STATUS_1, TransBizConstant.ACCOUNT_STATUS_2);
        List<AmAccountMainInfo> accountMainInfoList =
                extAmAccountMainInfoMapper.selectByLoanIdAndTypeAndCustomerIdAndBillingTenorAndStatusIn(
                        adjustAmountReq.getLoanId(), TransBizConstant.ACCOUNT_TYPE_12, adjustAmountReq.getCustomerId(),
                        adjustAmountReq.getBillingTenor(), statusList, null, tenantId);
        //新建总账流水list
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        //要更新的交易账户list
        List<AmAccountMainInfo> updateAccList = new ArrayList<>();

        //调整剩余金额
        BigDecimal currAdjustAmt = adjustAmountReq.getPostingAmount();
        //复利交易账户调整金额
        BigDecimal compoundAmt = BigDecimal.ZERO;


        //若交易账户不为空 调整交易信息
        if (CollectionUtils.isNotEmpty(accountMainInfoList)) {
            for (AmAccountMainInfo accountMainInfo : accountMainInfoList) {
                AmAccountMainInfo updateAcc = buildUpdateAcct(accountMainInfo);//获取要更新的交易账户
                updateAcc.setUpdateBy(userId);
                BigDecimal taxAmt = BigDecimal.ZERO;
                PrPenaltyRateTable prPenaltyRateTable = penaltyRateTableService.findByPenaltyId(accountMainInfo.getPenaltyTableId(), accountMainInfo.getOrganizationId(), accountMainInfo.getTenantId());
                //若调整金额大于当前账户余额 则调整金额为余额
                if (currAdjustAmt.compareTo(accountMainInfo.getCurrBalance()) > 0) {
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(accountMainInfo.getCurrBalance()));//调整金额
                    updateAcc.setCurrBalance(BigDecimal.ZERO);//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = accountMainInfo.getCurrBalance().multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }

                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            accountMainInfo.getCurrBalance().subtract(taxAmt), TransBizConstant.TXN_CODE_INST_COMP_INTR_T,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    currAdjustAmt = currAdjustAmt.subtract(accountMainInfo.getCurrBalance());//更新剩余调整金额
                    compoundAmt = compoundAmt.add(accountMainInfo.getCurrBalance());//更新复利交易账户调整金额
                } else { //若调整金额小等于当前账户余额
                    updateAcc.setCreditAdjustAmount(accountMainInfo.getCreditAdjustAmount().add(currAdjustAmt));//调整金额
                    updateAcc.setCurrBalance(accountMainInfo.getCurrBalance().subtract(currAdjustAmt));//余额

                    //价税分离
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = currAdjustAmt.multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                    }

                    //构建总账信息
                    TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo,
                            currAdjustAmt.subtract(taxAmt), TransBizConstant.TXN_CODE_INST_COMP_INTR_T,
                            accountMainInfo.getAccountingPhase(), businessDate);
                    if (tlGlInterfaceInfo != null) {
                        tlGlInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(tlGlInterfaceInfo);
                    }
                    compoundAmt = compoundAmt.add(currAdjustAmt);//更新复利交易账户调整金额
                    currAdjustAmt = BigDecimal.ZERO;//更新剩余调整金额为0

                }

                updateAcc.setTaxAmt(accountMainInfo.getTaxAmt().subtract(taxAmt));
                updateAccList.add(updateAcc); //放入更新列表
                TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(accountMainInfo, taxAmt, TransBizConstant.TXN_CODE_INST_COMP_INTR_TAX_T, accountMainInfo.getAccountingPhase(), businessDate);
                if (glInterfaceInfo != null) {
                    glInterfaceInfo.setUpdateBy(userId);
                    glInterfaceInfoList.add(glInterfaceInfo);
                }

                if (currAdjustAmt.compareTo(BigDecimal.ZERO) == 0) {
                    break;
                }
            }
        }
        //复利累计账户调整金额
        BigDecimal accrualAmt = BigDecimal.ZERO;
        //若复利交易账户调整后 剩余调整金额大于0  继续调整累计账户
        if (currAdjustAmt.compareTo(BigDecimal.ZERO) > 0) {
            //处理累计账户
            List<AmInterestAccrualInfo> interestAccrualInfoList =
                    extAmInterestAccrualInfoMapper.selectAccuAcct(adjustAmountReq.getLoanId(),
                            adjustAmountReq.getCustomerId(), tenantId, TransBizConstant.INTEREST_ACCRUAL_TYPE_20,
                            adjustAmountReq.getBillingTenor(), TransBizConstant.ACCOUNT_STATUS_1);

            if (CollectionUtils.isNotEmpty(interestAccrualInfoList)) {
                interestAccrualInfoList.sort(Comparator.comparing(AmInterestAccrualInfo::getAccrualStartDate).reversed());

                //复利累计不为空 修正复利累计
                for (AmInterestAccrualInfo interestAccrualInfo : interestAccrualInfoList) {
                    //构建要更新的累计账户信息
                    AmInterestAccrualInfo updateAccrual = buildUpdateAccrual(interestAccrualInfo);
                    updateAccrual.setUpdateBy(userId);
                    updateAccrual.setAccrualTotalAccruInterest(interestAccrualInfo.getAccrualTotalAccruInterest().subtract(currAdjustAmt));

                    //价税分离
                    BigDecimal taxAmt = BigDecimal.ZERO;
                    PrInterestTable prPenaltyRateTable = interestTableService.findInterestByInterestId(interestAccrualInfo.getInterestTableId(),  interestAccrualInfo.getTenantId());
                    if (TransBizConstant.TAX_FLAG_0.equals(prPenaltyRateTable.getTaxFlag())) {
                        //税金=含税收入金额/（1+税率）*税率计算每日利息的税金
                        taxAmt = currAdjustAmt.multiply(prPenaltyRateTable.getTaxRate()).divide(BigDecimal.ONE.add(prPenaltyRateTable.getTaxRate()), TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);
                        updateAccrual.setTaxAmt(interestAccrualInfo.getTaxAmt().subtract(taxAmt));
                        TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(interestAccrualInfo, taxAmt, TransBizConstant.TXN_CODE_COMP_INTR_TAX_REVOCATION, interestAccrualInfo.getAccountingPhase(), businessDate);
                        if (glInterfaceInfo != null) {
                            glInterfaceInfo.setUpdateBy(userId);
                            glInterfaceInfoList.add(glInterfaceInfo);
                        }
                    }
                    manuallyAdjustAccountSaveBean.addUpdateAccral(updateAccrual);
                    //构建总账信息
                    TlGlInterfaceInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(interestAccrualInfo, currAdjustAmt.subtract(taxAmt),
                            TransBizConstant.TXN_CODE_COMP_INTR_REVOCATION, interestAccrualInfo.getAccountingPhase(), businessDate);
                    if (glInterfaceInfo != null) {
                        glInterfaceInfo.setUpdateBy(userId);
                        glInterfaceInfoList.add(glInterfaceInfo);
                    }
                    accrualAmt = currAdjustAmt.add(currAdjustAmt);//更新复利累计账户调整金额
                }
            }

            //订单账户调整
            AmLoanAccountInfo loanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(adjustAmountReq.getLoanId(),
                    adjustAmountReq.getCustomerId(), tenantId);

            if (adjustAmountReq.getBillingTenor() <= loanAccountInfo.getCastTenor()) {
                AmLoanAccountInfo updateLoanAcct = buildUpdateLoanAcct(loanAccountInfo);//要更新的贷款账户
                updateLoanAcct.setUpdateBy(userId);
                updateLoanAcct.setCompoundBalance(loanAccountInfo.getPenaltyBalance().subtract(compoundAmt));//罚息余额
                updateLoanAcct.setAccruedCompound(loanAccountInfo.getAccruedPenalty().subtract(accrualAmt));//计提罚息
                manuallyAdjustAccountSaveBean.setTlGlInterfaceInfoList(glInterfaceInfoList);//总账信息
                manuallyAdjustAccountSaveBean.setUpdateAccList(updateAccList);//交易账户信息
                manuallyAdjustAccountSaveBean.setUpdateLoanAcct(updateLoanAcct);//贷款账户信息
            }

            manuallyAdjustAccountSaveBean.setAddTransInfo(transactionInfo);//交易信息

        }
    }


    /**
     * 验证是否在批处理中
     *
     * @param tenantId 租户id
     * @throws TxnBizException 批扣中不允许还款
     */
    private Date validateBatchProcessing(String tenantId,String orgId) throws TxnBizException {

        //判断当前机构是否在日终批量
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(orgId, tenantId);
        if(TransBizConstant.YES_FLAG.equals(organizationTable.getBatchInProgressFlag())){
            logger.error(TransErrMsgConstant.BATCH_PROCESSING);
            throw new TxnRuntimeException(TxnRespCode.BIZ_ERROR.getCode(),TransErrMsgConstant.BATCH_PROCESSING);
        }
        Integer count = extBtBatchStatusMapper.countByStatusAndJobName(TransBizConstant.BATCH_SATTUS_0,
                TransBizConstant.AUTO_PAYMENT, tenantId,organizationTable.getNextProcessingDate());
        //批扣中不允许还款
        if (count > 0) {
            logger.error(TransErrMsgConstant.AUTO_PAYMENT_PROCESSING);
            throw new TxnRuntimeException(TxnRespCode.BIZ_ERROR.getCode(),TxnRespCode.BIZ_ERROR.getUserTips());
        }

        return organizationTable.getNextProcessingDate();
    }

    /**
     * 保存手工交易调整信息
     * @param manuallyAdjustAccountSaveBean
     */
    private void updateManuallyAdjustInfo(ManuallyAdjustAccountSaveBean manuallyAdjustAccountSaveBean){
        if(manuallyAdjustAccountSaveBean.getUpdateRepaymentPlanInfo() != null){
            extAmRepaymentPlanInfoMapper.updateByIdAndCustomerIdAndTenantId(manuallyAdjustAccountSaveBean.getUpdateRepaymentPlanInfo());
        }

        if(manuallyAdjustAccountSaveBean.getAddTransInfo() != null){
            tlTransactionInfoMapper.insertSelective(manuallyAdjustAccountSaveBean.getAddTransInfo());
        }

        if(CollectionUtils.isNotEmpty(manuallyAdjustAccountSaveBean.getTlGlInterfaceInfoList())){
            extTlGlInterfaceInfoMapper.batchInsertSelective(manuallyAdjustAccountSaveBean.getTlGlInterfaceInfoList());
        }

        if(CollectionUtils.isNotEmpty(manuallyAdjustAccountSaveBean.getUpdateAccList())){
            extAmAccountMainInfoMapper.batchUpdateAccount(manuallyAdjustAccountSaveBean.getUpdateAccList());
        }

        if(CollectionUtils.isNotEmpty(manuallyAdjustAccountSaveBean.getUpdateAccralList())){
            extAmInterestAccrualInfoMapper.batchUpdateInterestAccrualInfo(manuallyAdjustAccountSaveBean.getUpdateAccralList());
        }

        if(manuallyAdjustAccountSaveBean.getUpdateLoanAcct() != null){
            extAmLoanAccountInfoMapper.updateByLoanId(manuallyAdjustAccountSaveBean.getUpdateLoanAcct());
        }
    }

    /**
     * 构建要修改的交易账户信息
     * @param accountMainInfo
     * @return
     */
    private AmAccountMainInfo buildUpdateAcct(AmAccountMainInfo accountMainInfo){
        AmAccountMainInfo updateAcc = new AmAccountMainInfo();
        updateAcc.setId(accountMainInfo.getId());
        updateAcc.setCustomerId(accountMainInfo.getCustomerId());
        updateAcc.setTenantId(accountMainInfo.getTenantId());
        return updateAcc;
    }

    /**
     * 构建要修改的累计账户信息
     * @param amInterestAccrualInfo
     * @return
     */
    private AmInterestAccrualInfo buildUpdateAccrual(AmInterestAccrualInfo amInterestAccrualInfo){
        AmInterestAccrualInfo updateAccrual = new AmInterestAccrualInfo();
        updateAccrual.setId(amInterestAccrualInfo.getId());
        updateAccrual.setCustomerId(amInterestAccrualInfo.getCustomerId());
        updateAccrual.setTenantId(amInterestAccrualInfo.getTenantId());
        return updateAccrual;
    }

    /**
     * 构建要修改的还款计划信息
     * @param repaymentPlanInfo
     * @return
     */
    private AmRepaymentPlanInfo buildUpdateRepaymentPlan(AmRepaymentPlanInfo repaymentPlanInfo){
        AmRepaymentPlanInfo updateRepaymentPlanInfo = new AmRepaymentPlanInfo();
        updateRepaymentPlanInfo.setId(repaymentPlanInfo.getId());
        updateRepaymentPlanInfo.setCustomerId(repaymentPlanInfo.getCustomerId());
        updateRepaymentPlanInfo.setTenantId(repaymentPlanInfo.getTenantId());
        return updateRepaymentPlanInfo;
    }

    /**
     * 要更新的贷款账户
     * @param amLoanAccountInfo
     * @return
     */
    private AmLoanAccountInfo buildUpdateLoanAcct(AmLoanAccountInfo amLoanAccountInfo){
        AmLoanAccountInfo updateLoanAcc = new AmLoanAccountInfo();
        updateLoanAcc.setLoanId(amLoanAccountInfo.getLoanId());
        updateLoanAcc.setCustomerId(amLoanAccountInfo.getCustomerId());
        updateLoanAcc.setTenantId(amLoanAccountInfo.getTenantId());
        return updateLoanAcc;
    }
}
